package com.aioz.security.service.impl;

import cn.hutool.core.util.StrUtil;
import com.aioz.security.common.ResponseResult;
import com.aioz.security.entity.Follow;
import com.aioz.security.entity.LoginUser;
import com.aioz.security.entity.Notify;
import com.aioz.security.entity.dto.ScrollResult;
import com.aioz.security.mapper.NotifyMapper;
import com.aioz.security.service.NotifyService;
import com.aioz.security.utils.RedisCache;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.aioz.security.common.RedisConstants.FEED_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Aioz
 * @since 2022-10-28
 */
@Service
public class NotifyServiceImpl extends ServiceImpl<NotifyMapper, Notify> implements NotifyService {

    @Resource
    private FollowServiceImpl followService;

    @Resource
    private CompanyServiceImpl companyService;

    @Resource
    private RedisCache redisCache;

    @Override
    public ResponseResult publish(Notify notify) {
        //获取企业ID
        Integer companyId = notify.getCompanyId();
        //企业名称是否为空
        if("".equals(notify.getCompany())){
          notify.setCompany( companyService.getById(companyId).getName());
        }
        // 保存消息
        boolean isSuccess = save(notify);
        if(!isSuccess){
            return new ResponseResult<>(409,"消息新增失败！");
        }
        //查询企业所有的关注用户
        List<Follow> follows = followService.query().eq("company_id", companyId).list();
        //推送消息给关注用户
        for (Follow follow : follows) {
            //获取关注用户ID
            Integer userId = follow.getUserId();
            //推送
            String key = "feed:" + userId;
            redisCache.setCacheZSet(key,notify.getId().toString());
        }
        //返回消息ID
        return new ResponseResult<>(200,notify.getId());
    }

    /*
    *  max 时间戳
    *  offset 偏移量
    * */
    @Override
    public ResponseResult queryNotifyOfFollow(Long max, Integer offset) {
        // 获取当前用户
        Long userId = getCurrentUserId();
        //查询收件箱
        String key = FEED_KEY + userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples =
                redisCache.getCacheZSet(key, max, offset);
        //非空判断
        if(typedTuples == null || typedTuples.isEmpty()){
            return new ResponseResult<>(200,"暂无消息");
        }
        //解析收件箱的数据: notifyId , minTime(时间戳) , offset
        List<Integer> ids = new ArrayList<>(typedTuples.size());
        long minTime = 0;
        int os = 1;
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
            //获取ID
            ids.add(Integer.parseInt(tuple.getValue()));
            //获取分数(时间戳)
            long time = tuple.getScore().longValue();
            if(time == minTime){
                os++;
            }else {
                minTime = time;
                os = 1;
            }
        }
        //根据 notifyId 查到 notify
        String idStr = StrUtil.join(",", ids);
        List<Notify> notifies = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();
        for (Notify notify : notifies) {
            // 浏览次数 + 1
            notify.setReadCount(notify.getReadCount() + 1);
            updateById(notify);
        }
        ScrollResult scroll = new ScrollResult();
        scroll.setList(notifies);
        scroll.setMinTime(minTime);
        scroll.setOffset(os);
        //封装返回
        return new ResponseResult<>(200,scroll);
    }

    @Override
    public ResponseResult getOwnNotifies(Integer id) {
        List<Notify> notifies = query().eq("company_id", id).list();
        return new ResponseResult<>(200,notifies);
    }


    public Long getCurrentUserId(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        return loginUser.getUser().getId();
    }

    public ResponseResult deleteNotifyById(Integer id) {
        boolean isSuccess = removeById(id);
        if(isSuccess){
            return new ResponseResult<>(200,"消息已删除");
        }
        return new ResponseResult(200,"系统异常，消息删除失败");
    }
}
